
 
 import java.awt.AWTException;
 import java.awt.Rectangle;
 import java.awt.Robot;
 import java.awt.Toolkit;
 import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
 import java.io.File;
import java.io.FileOutputStream;
 import java.io.IOException;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
 
import javax.imageio.ImageIO;
 /**
  * 屏幕上查找指定图片
  * @author Jeby Sun
  * @date 2014-09-13 
  */
 public class ImageFindDemo {
//     
//     BufferedImage screenShotImage;    //屏幕截图
//     BufferedImage keyImage;           //查找目标图片
//     
//     int scrShotImgWidth;              //屏幕截图宽度
//     int scrShotImgHeight;             //屏幕截图高度
//     
//     int keyImgWidth;                  //查找目标图片宽度
//     int keyImgHeight;                 //查找目标图片高度
//     
//     int[][] screenShotImageRGBData;   //屏幕截图RGB数据
//     int[][] keyImageRGBData;          //查找目标图片RGB数据
//     
//     int[][][] findImgData;            //查找结果，目标图标位于屏幕截图上的坐标数据 
     
//     public ImageFindDemo(String keyImagePath) {
//         screenShotImage = this.getFullScreenShot();
//         keyImage = this.getBfImageFromPath(keyImagePath);
//         screenShotImageRGBData = this.getImageGRB(screenShotImage);
//         keyImageRGBData = this.getImageGRB(keyImage);
//         scrShotImgWidth = screenShotImage.getWidth();
//         scrShotImgHeight = screenShotImage.getHeight();
//         keyImgWidth = keyImage.getWidth();
//         keyImgHeight = keyImage.getHeight();
//         
//         //开始查找
//         this.findImage();
         
//     }
     
     /**
      * 全屏截图
      * @return 返回BufferedImage
      */
     public BufferedImage getFullScreenShot() {
         BufferedImage bfImage = null;
         int width = (int) Toolkit.getDefaultToolkit().getScreenSize().getWidth();
         int height = (int) Toolkit.getDefaultToolkit().getScreenSize().getHeight();
         try {
             Robot robot = new Robot();
             bfImage = robot.createScreenCapture(new Rectangle(0, 0, width, height));
         } catch (AWTException e) {
             e.printStackTrace();
         }
         return bfImage;
     }
     
     /**
      * 从本地文件或者http请求的文件读取目标图片
      * @param keyImagePath - 图片绝对路径
      * @return 本地图片的BufferedImage对象
      */
     public BufferedImage getBfImageFromPath(String imgurl) {
    	 String lower=imgurl.toLowerCase();
         BufferedImage bi = null;
         try {
	         if(lower.indexOf("http://")!=-1||lower.indexOf("https://")!=-1){
	              //实例化url
	             URL url = new URL(imgurl);
	             //载入图片到输入流
	             BufferedInputStream bis = new BufferedInputStream(url.openStream());
	             bi=ImageIO.read(bis);
	         }else{//直接是文件流
	        	 bi=ImageIO.read(new File(imgurl));
	         }
	     } catch (IOException e) {
	         e.printStackTrace();
	     }
        return bi;
     }
   
     /**
      * 根据BufferedImage获取图片RGB数组
      * @param bfImage
      * @return
      */
     public int[][] getImageGRB(BufferedImage bfImage) {
         int width = bfImage.getWidth();
         int height = bfImage.getHeight();
         int[][] result = new int[height][width];
         for (int h = 0; h < height; h++) {
             for (int w = 0; w < width; w++) {
                 //使用getRGB(w, h)获取该点的颜色值是ARGB，而在实际应用中使用的是RGB，所以需要将ARGB转化成RGB，即bufImg.getRGB(w, h) & 0xFFFFFF。
                 result[h][w] = bfImage.getRGB(w, h) & 0xFFFFFF;
             }
         }
         return result;
     }
     
     
     /**
      * 查找图片
      */
     public boolean findImage(String keyImagePath,String findPath,double xs) {
    	 BufferedImage screenShotImage = this.getBfImageFromPath(findPath);//对比对象
    	 BufferedImage keyImage = this.getBfImageFromPath(keyImagePath);//需查找图像
    	 int[][] screenShotImageRGBData = this.getImageGRB(screenShotImage);//RGB数据
    	 int[][] keyImageRGBData = this.getImageGRB(keyImage);//RGB数据
         int scrShotImgWidth = screenShotImage.getWidth();
         int scrShotImgHeight = screenShotImage.getHeight();
         int keyImgWidth = keyImage.getWidth();
         int keyImgHeight = keyImage.getHeight();
         
    	 int biggerY = 0;
         int biggerX = 0;
         int xor = 0;
         int all=keyImgHeight*keyImgWidth;
         int not=all;
         int lxNot=0;//连续多小点不是
         double lx=2;//keyImgWidth*0.3;
         double diNot=xs*all;
         boolean find=true;//是否查到
         int xsd=0;
         //遍历屏幕截图像素点数据
         for(int y=0,h=scrShotImgHeight-keyImgHeight; y<=h; y++) {
             for(int x=0,w=scrShotImgWidth-keyImgWidth; x<=w; x++) {
                 //根据目标图的尺寸，得到目标图四个角映射到屏幕截图上的四个点，
                 //判断截图上对应的四个点与图B的四个角像素点的值是否相同，
                 //如果相同就将屏幕截图上映射范围内的所有的点与目标图的所有的点进行比较。
            	 //pb add 起点10%的面积有90% 相同 则进入
//                 if((keyImageRGBData[0][0]^screenShotImageRGBData[y][x])==0
//                         && (keyImageRGBData[0][keyImgWidth-1]^screenShotImageRGBData[y][x+keyImgWidth-1])==0
//                         && (keyImageRGBData[keyImgHeight-1][keyImgWidth-1]^screenShotImageRGBData[y+keyImgHeight-1][x+keyImgWidth-1])==0
//                         && (keyImageRGBData[keyImgHeight-1][0]^screenShotImageRGBData[y+keyImgHeight-1][x])==0
//                		 ) {
//                     
//                     boolean isFinded = isMatchAll(y, x,0.95);
//                     //如果比较结果完全相同，则说明图片找到，填充查找到的位置坐标数据到查找结果数组。
//                     if(isFinded) {
////                         for(int h=0; h<keyImgHeight; h++) {
////                             for(int w=0; w<keyImgWidth; w++) {
////                                 findImgData[h][w][0] = y+h; 
////                                 findImgData[h][w][1] = x+w;
////                             }
////                         }
//                         System.out.println("找到相似");
//                         return;
//                     }
//                 }
            	 not=all;
            	 find=true;
            	 lxNot=0;
//            if((keyImageRGBData[0][0]^screenShotImageRGBData[y][x])==0
//               && (keyImageRGBData[0][keyImgWidth-1]^screenShotImageRGBData[y][x+keyImgWidth-1])==0
//               && (keyImageRGBData[keyImgHeight-1][keyImgWidth-1]^screenShotImageRGBData[y+keyImgHeight-1][x+keyImgWidth-1])==0
//               && (keyImageRGBData[keyImgHeight-1][0]^screenShotImageRGBData[y+keyImgHeight-1][x])==0
//      		 ) {
                 for(int smallerY=0; smallerY<keyImgHeight; smallerY++) {
                     biggerY = y+smallerY;
                     for(int smallerX=0; smallerX<keyImgWidth; smallerX++) {
                         biggerX = x+smallerX;
                         if(biggerY>=scrShotImgHeight || biggerX>=scrShotImgWidth) {
                        	 find=false;
                        	 break;
                         }
                         xor = keyImageRGBData[smallerY][smallerX]^screenShotImageRGBData[biggerY][biggerX];
//                         if(xsd==0){
//                        	 xsd=xor;
//                        	 System.out.println(xsd);
//                         }
                     if(xor!=0) {
                        	 not--;
                        	 if(not<diNot){
                        		 find=false;
                        		 break;
                        	 }
                        	 if(smallerY==0){
	                        	 lxNot++;
	                        	 if(lxNot>lx){//连续大于这么多点不匹配则重新配置下一个位置
	                        		 find=false;
	                        		 break;
	                        	 }
                        	 }
                         }
                     }
                     if(!find){
                    	 break;
                     }
                 }
                 if(find){
                	 System.out.println(String.format("起始坐标x:%s,y:%s", x,y));
                	 return true;
                 }
//               }
             }
         }
         return false;
     }
     
//     /**
//      * 判断屏幕截图上目标图映射范围内的全部点是否全部和小图的点一一对应。
//      * @param y - 与目标图左上角像素点想匹配的屏幕截图y坐标
//      * @param x - 与目标图左上角像素点想匹配的屏幕截图x坐标
//      * @param xs -- 相似度
//      * @return
//      */
//     public boolean isMatchAll(int y, int x,double xs) { 
//    	 int biggerY = 0;
//         int biggerX = 0;
//         int xor = 0;
//         int all=keyImgHeight*keyImgWidth;
//         int not=all;
//         double diNot=xs*all;
//         for(int smallerY=0; smallerY<keyImgHeight; smallerY++) {
//             biggerY = y+smallerY;
//             for(int smallerX=0; smallerX<keyImgWidth; smallerX++) {
//                 biggerX = x+smallerX;
//                 if(biggerY>=scrShotImgHeight || biggerX>=scrShotImgWidth) {
//                     return false;
//                 }
//                 xor = keyImageRGBData[smallerY][smallerX]^screenShotImageRGBData[biggerY][biggerX];
//                 if(xor!=0) {
//                	 not--;
//                	 if(not<diNot){
//                		 return false;
//                	 }
//                 }
//             }
//             biggerX = x;
//         }
//         return true;
//     }
//     
//     /**
//      * 输出查找到的坐标数据
//      */
//     private void printFindData() {
//         for(int y=0; y<keyImgHeight; y++) {
//             for(int x=0; x<keyImgWidth; x++) {
//                 System.out.print("("+this.findImgData[y][x][0]+", "+this.findImgData[y][x][1]+")");
//             }
//             System.out.println();
//         }
//     }
 
     
     public static void main(String[] args) {
         try {
			ImageFindDemo demo = new ImageFindDemo();
			 double xs=0.9;
			 boolean find=demo.findImage("D:/key2.png","http://119.29.140.160/key1.png",xs);
			 if(find){
				 System.out.println(String.format("图片匹配成功,相似度大于%s",xs));
			 }else{
				 System.out.println("图片不匹配");
			 }
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
         
     }
 
 }